package com.xaicode.learn.java.forkjoin;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author Locker cjxia@isoftstone.com
 * @version 1.0
 */
public class ForkJoinTaskDemo {

    private static transient volatile AtomicInteger forkJoinCount = new AtomicInteger(0);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        CountTask task = new CountTask(1, 5);
        Future<Integer> result = forkJoinPool.submit(task);
        System.out.println("1~5 add result: " + result.get());

        CountTask task2 = new CountTask(1, 100);
        Future<Integer> result2 = forkJoinPool.submit(task2);
        System.out.println("1~100 add result: " + result2.get());
    }

    static class CountTask extends RecursiveTask<Integer> {

        private static int splitSize = 2;
        private int start, end;

        public CountTask(int start, int end) {
            this.start = start;
            this.end = end;
        }

        @Override
        protected Integer compute() {
            int sum = 0;
            boolean canCompute = (end - start) <= splitSize;
            if (canCompute) {
                for (int i = start; i <= end; i++) {
                    sum = sum + i;
                }
            } else {
                // split task
                int middle = (start + end) / 2;

                System.out.printf("origin: start=%d, end=%d\n", start, end);
                System.out.printf("forkJoin split: start=%d, middle=%d, end=%d\n", start, middle, end);

                CountTask firstTask = new CountTask(start, middle);
                CountTask secondTask = new CountTask(middle + 1, end);
                firstTask.fork();
                secondTask.fork();
                // wait done
                int firstResult = firstTask.join();
                int secondResult = secondTask.join();
                // 合并
                sum = firstResult + secondResult;
            }

            return sum;
        }
    }

}
